package cvutils

import (
	"image"

	"face_search/src/my_utils/commons"

	"github.com/sirupsen/logrus"
	"gocv.io/x/gocv"
)

func CloseClassifier(classifier *gocv.CascadeClassifier) {
	err := classifier.Close()
	if err != nil {
	}
}

func DetectImgFace(img image.Image) []image.Rectangle {
	mat, err := gocv.ImageToMatRGB(img)
	if err != nil {
		logrus.Error(commons.GetErrorStack(err, "image转mat失败"))
		return nil
	}
	defer matClose(&mat)
	grayMat := gocv.NewMat()
	defer matClose(&grayMat)
	gocv.CvtColor(mat, &grayMat, gocv.ColorBGRToGray)
	gocv.EqualizeHist(grayMat, &grayMat)

	minSz := image.Point{
		X: 55,
		Y: 55,
	}

	maxSz := image.Point{
		X: img.Bounds().Max.X - 55,
		Y: img.Bounds().Max.Y - 55,
	}

	faceClassifier := gocv.NewCascadeClassifier()
	if !faceClassifier.Load("resource/haarcascade_frontalface_alt.xml") {
		logrus.Error("加载face资源文件失败")
	}
	faces := faceClassifier.DetectMultiScaleWithParams(grayMat, 1.0730499, 0, 1, minSz, maxSz)
	faceClassifier.Close()

	return faces
}

func DetectImgEye(img image.Image) []image.Rectangle {
	mat, err := gocv.ImageToMatRGB(img)
	if err != nil {
		logrus.Error(commons.GetErrorStack(err, "image转mat失败"))
		return nil
	}
	defer matClose(&mat)
	grayMat := gocv.NewMat()
	defer matClose(&grayMat)
	gocv.CvtColor(mat, &grayMat, gocv.ColorBGRToGray)
	gocv.EqualizeHist(grayMat, &grayMat)

	eyeClassifier := gocv.NewCascadeClassifier()
	if !eyeClassifier.Load("resource/haarcascade_lefteye_2splits.xml") {
		logrus.Fatalf("加载eye资源文件失败")
	}
	eyes := eyeClassifier.DetectMultiScale(grayMat)
	eyeClassifier.Close()

	return eyes
}

func CutImg(rect image.Rectangle, img image.Image) image.Image {
	mat, err := gocv.ImageToMatRGB(img)
	defer matClose(&mat)
	if err != nil {
		logrus.Error(commons.GetErrorStack(err, "image转mat失败"))
		return nil
	}
	min := rect.Min
	max := rect.Max
	if 0 <= min.X && 0 <= max.X && max.X <= mat.Cols() && 0 <= min.Y && 0 <= max.Y && max.Y <= mat.Rows() {
		if min.X-15 >= 0 && max.X+15 <= mat.Cols() {
			min.X = min.X - 15
			max.X = max.X + 15
		}
		if min.Y-10 >= 0 && max.Y+10 <= mat.Rows() {
			min.Y = min.Y - 10
			max.Y = max.Y + 10
		}
	}

	cutRect := image.Rect(min.X, min.Y, max.X, max.Y)

	region := mat.Region(cutRect)
	defer matClose(&region)
	newSize := image.Point{
		X: 350,
		Y: 350,
	}
	newMat := gocv.NewMat()
	defer matClose(&newMat)
	gocv.Resize(region, &newMat, newSize, 0, 0, gocv.InterpolationLinear)
	resultImg, matToImageErr := newMat.ToImage()
	if matToImageErr != nil {
		logrus.Error("mat转image异常", matToImageErr.Error())
	}
	return resultImg
}

func matClose(mat *gocv.Mat) {
	err := mat.Close()
	if err != nil {
		logrus.Error("释放mat失败", err)
		mat = nil
	}
}
